package main

import (
	"net"
	"strings"
)

type User struct {
	Name   string
	Addr   string
	C      chan string
	conn   net.Conn
	server *Server
}

// 创建一个用户的方法API
func NewUser(conn net.Conn, server *Server) *User {
	userAddr := conn.RemoteAddr().String()

	user := &User{
		Name:   userAddr,
		Addr:   userAddr,
		C:      make(chan string),
		conn:   conn,
		server: server,
	}

	// 启动当前user channel消息的goroutine
	go user.ListenMessage()

	return user
}

// 用户的上线业务
func (s *User) Online() {
	// 用户上线，将用户加入到onlineMap中
	s.server.mapLock.Lock()
	s.server.OnlineMap[s.Name] = s
	s.server.mapLock.Unlock()

	// 广播当前用户上线信息
	s.server.BroadCast(s, "已上线")

}

// 用户的下线业务
func (s *User) Offline() {
	// 用户下线，将用户从onlineMap中删除
	s.server.mapLock.Lock()
	delete(s.server.OnlineMap, s.Name)
	s.server.mapLock.Unlock()

	// 广播当前用户下线信息
	s.server.BroadCast(s, "下线")
}

// 当前User对应的客户端发送消息
func (s *User) SendMsg(msg string) {
	s.conn.Write([]byte(msg))
}

// 用户的用户消息的业务
func (s *User) DoMessage(msg string) {
	if msg == "who" {
		// 查询当前在线用户都有哪些
		s.server.mapLock.Lock()
		for _, user := range s.server.OnlineMap {
			onlineMsg := "[" + user.Addr + "]" + user.Name + ":" + "在线...\n"
			s.SendMsg(onlineMsg)
		}
		s.server.mapLock.Unlock()

	} else if len(msg) > 7 && msg[:7] == "rename|" {
		// 消息格式:rename|张三
		newName := strings.Split(msg, "|")[1]

		// 判断name是否存在
		_, ok := s.server.OnlineMap[newName]
		if ok {
			s.SendMsg("当前用户名已被使用\n")
		} else {
			s.server.mapLock.Lock()
			delete(s.server.OnlineMap, s.Name)
			s.server.OnlineMap[newName] = s
			s.server.mapLock.Unlock()

			s.Name = newName
			s.SendMsg("您已经更新用户名：" + s.Name + "\n")
		}

	} else if len(msg) > 4 && msg[:3] == "to|" {
		// 消息格式：to|张三|消息内容

		// 1 获取对方用户名
		remoteName := strings.Split(msg, "|")[1]
		if remoteName == "" {
			s.SendMsg("消息格式不正确，请使用\"to|张三|消息内容\"格式\n")
		}

		// 2 根据用户名得到对方的User对象
		remoteUser, ok := s.server.OnlineMap[remoteName]
		if !ok {
			s.SendMsg("该用户名不存在，私聊无法进行\n")
			return
		}
		// 3 获取消息内容，通过对方的User发送消息过去
		context := strings.Split(msg, "|")[2]
		if context == "" {
			s.SendMsg("无消息内容，请重发")
			return
		}
		remoteUser.SendMsg(s.Name + " 对您说：" + context + "\n")

	} else {
		s.server.BroadCast(s, msg)
	}
}

// 监听当前User channel的方法 一旦有消息，就直接发送给客户端
func (s *User) ListenMessage() {
	for {
		msg := <-s.C

		s.conn.Write([]byte(msg + "\n"))
	}
}
